// 三种状态 等待 成功 失败
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';

class MyPromise {
    constructor(executor) {
        // 状态 默认pending
        this.status = PENDING;
        // 成功值
        this.value = void 0;
        // 失败原因
        this.reason = void 0;
        // 当executor为异步的成功回调缓存
        this.successCallback = [];
        // 当executor为异步的失败回调缓存
        this.errorCallback = [];
        try {
            executor(this.resolve, this.reject);
        } catch (e) {
            this.reject(e);
        }

    }

    // resolve需绑定当前Promise对象
    resolve = (value) => {
        //状态已改变，返回
        if (this.status !== PENDING) {
            return;
        }
        //状态置为成功
        this.status = FULFILLED;
        // 保存成功值
        this.value = value;
        // 如果excutor为异步的回调循环
        while (this.successCallback.length) {
            this.successCallback.shift()();
        }
    }
    // reject需绑定当前Promise对象
    reject = (reason) => {
        if (this.status !== PENDING) {
            return;
        }
        //状态置为失败
        this.status = REJECTED;
        // 保存失败原因
        this.reason = reason;
        // 如果excutor为异步的失败回调循环
        while (this.errorCallback.length) {
            this.errorCallback.shift()();
        }
    }

    then(successCallback, errorCallback) {
        // successCallback默认传递当前返回至下一个，以形成空then调用
        successCallback = successCallback || (value => value);
        errorCallback = errorCallback || (reason => {
            // errorCallback即为reject方法，reject方法本身报错，无法再执行reject(reason)，直接抛出异常
            throw reason
        });
        let promise2 = new MyPromise((resolve, reject) => {
            // executor使用箭头函数，里面的this指向外部的then所在对象，即当前对象
            // 同步executor的成功回调
            if (this.status === FULFILLED) {
                setTimeout(() => {
                    try {
                        // 可以理解为this为上个promise，successCallback(this.value)即调用上个对象的resolve(value)，其返回值是下一个promise
                        let result = successCallback(this.value);
                        resolvePromise(promise2, result, resolve, reject);
                    } catch (e) {
                        reject(e);
                    }
                })
            } else if (this.status === REJECTED) {
                //同步executor的失败回调
                setTimeout(() => {
                    try {
                        let result = errorCallback(this.reason);
                        resolvePromise(promise2, result, resolve, reject);
                    } catch (e) {
                        reject(e);
                    }
                })
            } else {
                //异步的executor回调，先缓存再执行
                //使用箭头函数包裹，确保callback是函数
                this.successCallback.push(() => {
                    setTimeout(() => {
                        try {
                            // 可以理解为this为上个promise，successCallback(this.value)即调用上个对象的resolve(value)，其返回值是下一个promise
                            let result = successCallback(this.value);
                            resolvePromise(promise2, result, resolve, reject);
                        } catch (e) {
                            reject(e);
                        }
                    })
                })
                this.errorCallback.push(() => {
                    setTimeout(() => {
                        try {
                            let result = errorCallback(this.reason);
                            resolvePromise(promise2, result, resolve, reject);
                        } catch (e) {
                            reject(e);
                        }
                    })
                })
            }
        })
        // 返回为Promise，链式调用
        return promise2;
    }

    catch(errorCallback) {
        // catch为then的语法糖
        return this.then(undefined, errorCallback);
    }

    finally(callback) {
        return this.then((value) => {
            // 将callback结果包装为promise
            return MyPromise.resolve(callback()).then(() => value);
            //返回当前promise value

        }, (e) => {
            return MyPromise.resolve(callback())
                .then(() => {
                    throw e
                })
        })
    }

    //resolve，静态方法，用于快速返回一个promise
    static resolve(value) {
        if (value instanceof MyPromise) {
            return MyPromise;
        }
        return new Promise((resolve) => {
            resolve(value)
        })
    }

    //当所有任务均成功，则成功，返回一个promise，value为执行任务结果的数组
    // 有任意一个报错，则reject
    static all(array) {
        let result = [];
        let count = 0;
        return new MyPromise((resolve, reject) => {
            function addData(index, value) {
                result[index] = value;
                count++;
                if (count === array.length) {
                    resolve(result);
                }
            }

            try {
                for (let i = 0; i < array.length; i++) {
                    let current = array[i];
                    // 当前任务为promise对象
                    if (current instanceof MyPromise) {
                        current.then((value) => {
                            addData(i, value)
                        }, reason => {
                            reject(reason);
                        })
                    } else {
                        addData(i, current);
                    }
                }
            } catch (e) {
                reject(e);
            }

        })
    }

    //返回最快的那个执行任务结果，可以是resolve或者reject
    static race(array) {
        return new MyPromise((resolve, reject) => {
            for (let i = 0; i < array.length; i++) {
                let current = array[i];
                setTimeout(() => {
                    //闭包
                    try {
                        if (current instanceof MyPromise) {
                            current.then((value) => {
                                resolve(value);
                            }, reason => {
                                reject(reason);
                            })
                        } else {
                            resolve(current);
                        }
                    } catch (e) {
                        reject(e);
                    }

                })
            }
        })
    }
}

function resolvePromise(promise2, result, resolve, reject) {
    if (promise2 === result) {
        // 此处的error在then中catch
        return reject(new TypeError('Chaining Promise Error'));
    }
    // 若返回为promise，执行，可以理解为递归直到取到返回值
    if (result instanceof MyPromise) {
        result.then(resolve, reject)
    } else {
        resolve(result);
    }
}

module.exports = MyPromise;